package controladores;

import entidades.RegistroInteresse;
import entidades.Util;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;

/**
 * Classe responsável pelas operações de transações que ocorrem no servidor.
 *
 */
public class ControladoraTransacoes {

    /**
     * Método que fica sempre em execução e é disparado sempre que um novo registro é inserido no servidor (de compra ou de venda).
     * Verifica se é possível realizar alguma transação, e, caso seja, a realiza e notifica os acionistas envolvidos.     
     */
    public void completarTransacoesPossiveis() {
        while (true) {
            if (Util.houveNovosRegistros()) {
                Util.negarNovoRegistro();
                for (int indiceCompra = 0; indiceCompra < Util.compras.size(); indiceCompra++) {
                    for (int indiceVenda = 0; indiceVenda < Util.vendas.size(); indiceVenda++) {
                        RegistroInteresse compra = (RegistroInteresse) Util.compras.get(indiceCompra);
                        RegistroInteresse venda = (RegistroInteresse) Util.vendas.get(indiceVenda);

                        //Se não é do mesmo acionista o registro de venda e de compra
                        if (!compra.getCaminhoCliente().equals(venda.getCaminhoCliente())) {
                            //Se a empresa e o preço da ação são compatíveis
                            if (compra.getAcao().getEmpresa().equals(venda.getAcao().getEmpresa())
                                    && compra.getPreco() >= venda.getPreco()) {

                                double precoFinal = (compra.getPreco() + venda.getPreco()) / 2;

                                //Se um acionista quer comprar menos ações do que outro está vendendo
                                if (compra.getAcao().getQuantidade() < venda.getAcao().getQuantidade()) {
                                    venda.getAcao().setQuantidade(venda.getAcao().getQuantidade() - compra.getAcao().getQuantidade());
                                    Util.compras.remove(compra);
                                    try {
                                        //Notifica o comprador
                                        XmlRpcClient clientCompra = obterReferenciaCliente(compra.getCaminhoCliente());
                                        ArrayList parametrosCompra = new ArrayList();
                                        parametrosCompra.add(compra.getAcao().getEmpresa());
                                        parametrosCompra.add(compra.getTempoInicial());
                                        parametrosCompra.add(compra.getAcao().getQuantidade());
                                        parametrosCompra.add(precoFinal);
                                        clientCompra.execute("notificarCompraEfetuada", parametrosCompra);

                                        //Notifica o vendedor
                                        XmlRpcClient clientVenda = obterReferenciaCliente(venda.getCaminhoCliente());
                                        ArrayList parametrosVenda = new ArrayList();
                                        parametrosVenda.add(venda.getAcao().getEmpresa());
                                        parametrosVenda.add(venda.getTempoInicial());
                                        parametrosVenda.add(compra.getAcao().getQuantidade());
                                        parametrosVenda.add(precoFinal);
                                        clientVenda.execute("notificarVendaEfetuada", parametrosVenda);
                                    } catch (MalformedURLException ex) {
                                        Logger.getLogger(ControladoraTransacoes.class.getName()).log(Level.SEVERE, null, ex);
                                    } catch (XmlRpcException ex) {
                                        Logger.getLogger(ControladoraTransacoes.class.getName()).log(Level.SEVERE, null, ex);
                                    }
                                    Util.janelaPrincipal.inserirLog("Efetivei transação de " + compra.getAcao().getQuantidade() + " ações da empresa " + compra.getAcao().getEmpresa() + "\n");
                                    Util.indicarNovoRegistro();
                                    //Se um acionista quer comprar mais ações do que outro está vendendo
                                } else if (compra.getAcao().getQuantidade() > venda.getAcao().getQuantidade()) {
                                    compra.getAcao().setQuantidade(compra.getAcao().getQuantidade() - venda.getAcao().getQuantidade());
                                    Util.vendas.remove(venda);
                                    try {
                                        //Notifica o comprador
                                        XmlRpcClient clientCompra = obterReferenciaCliente(compra.getCaminhoCliente());
                                        ArrayList parametrosCompra = new ArrayList();
                                        parametrosCompra.add(compra.getAcao().getEmpresa());
                                        parametrosCompra.add(compra.getTempoInicial());
                                        parametrosCompra.add(venda.getAcao().getQuantidade());
                                        parametrosCompra.add(precoFinal);
                                        clientCompra.execute("notificarCompraEfetuada", parametrosCompra);

                                        //Notifica o vendedor
                                        XmlRpcClient clientVenda = obterReferenciaCliente(venda.getCaminhoCliente());
                                        ArrayList parametrosVenda = new ArrayList();
                                        parametrosVenda.add(venda.getAcao().getEmpresa());
                                        parametrosVenda.add(venda.getTempoInicial());
                                        parametrosVenda.add(venda.getAcao().getQuantidade());
                                        parametrosVenda.add(precoFinal);
                                        clientVenda.execute("notificarVendaEfetuada", parametrosVenda);
                                    } catch (MalformedURLException ex) {
                                        Logger.getLogger(ControladoraTransacoes.class.getName()).log(Level.SEVERE, null, ex);
                                    } catch (XmlRpcException ex) {
                                        Logger.getLogger(ControladoraTransacoes.class.getName()).log(Level.SEVERE, null, ex);
                                    }
                                    Util.janelaPrincipal.inserirLog("Efetivei transação de " + venda.getAcao().getQuantidade() + " ações da empresa " + compra.getAcao().getEmpresa() + "\n");
                                    Util.indicarNovoRegistro();
                                    //Se um acionista quer comprar o mesmo número de ações do que outro está vendendo
                                } else {
                                    Util.compras.remove(compra);
                                    Util.vendas.remove(venda);

                                    try {
                                        //Notifica o vendedor
                                        XmlRpcClient clientVenda = obterReferenciaCliente(venda.getCaminhoCliente());
                                        ArrayList parametrosVenda = new ArrayList();
                                        parametrosVenda.add(venda.getAcao().getEmpresa());
                                        parametrosVenda.add(venda.getTempoInicial());
                                        parametrosVenda.add(venda.getAcao().getQuantidade());
                                        parametrosVenda.add(precoFinal);
                                        clientVenda.execute("notificarVendaEfetuada", parametrosVenda);

                                        //Notifica o comprador
                                        XmlRpcClient clientCompra = obterReferenciaCliente(compra.getCaminhoCliente());
                                        ArrayList parametrosCompra = new ArrayList();
                                        parametrosCompra.add(compra.getAcao().getEmpresa());
                                        parametrosCompra.add(compra.getTempoInicial());
                                        parametrosCompra.add(compra.getAcao().getQuantidade());
                                        parametrosCompra.add(precoFinal);
                                        clientCompra.execute("notificarCompraEfetuada", parametrosCompra);
                                    } catch (MalformedURLException ex) {
                                        Logger.getLogger(ControladoraTransacoes.class.getName()).log(Level.SEVERE, null, ex);
                                    } catch (XmlRpcException ex) {
                                        Logger.getLogger(ControladoraTransacoes.class.getName()).log(Level.SEVERE, null, ex);
                                    }
                                    Util.janelaPrincipal.inserirLog("Efetivei transação de ações da empresa " + compra.getAcao().getEmpresa() + "\n");
                                    Util.indicarNovoRegistro();
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Dado um camimnho de conexão, retorna uma referencia para o cliente do
     * tipo XmlRpcClient.
     *
     * @param caminhoConexao
     * @return referencia para o cliente
     * @throws MalformedURLException Caso o caminho esteja incorreto
     */
    private XmlRpcClient obterReferenciaCliente(String caminhoConexao) throws MalformedURLException {
        XmlRpcClient client = null;
        client = new XmlRpcClient();
        XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
        config.setServerURL(new URL(caminhoConexao));
        config.setEnabledForExtensions(true);
        client.setConfig(config);
        return client;
    }
}
